-----------------------------------------------------------------------------
-- 游戏层通用函数封装
--
---------------
-- @author wudi
-----------------------------------------------------------------------------
HelperFunc = {}

--- 获取服务器时间 默认返回秒   false返回毫秒
function HelperFunc.GetServerTime(second)
	if second == nil then second = true end
	if second then
		return Config.serverTime * 0.001
	end
	return Config.serverTime
end

--- 获取常量表中的 字符串内容
-- 不做判空处理,报错 找策划
function HelperFunc.GetGlobalVlue(key)
	return decodeJsonStrToTabel(G.dataTable["t_global"][tostring(key)]["f_string_value"])
end

--- 获取常量表中的 常量值
function HelperFunc.GetGlobalNumVlue(key)
	return G.dataTable["t_global"][tostring(key)]["f_int_value"]
end

--- 全同步是否完成
function HelperFunc.GetSyncAttrAllFinish()
	return Config.SyncAttrAllFinish
end

--- 获取策划配表名称
function HelperFunc.GetDefaultName()
	return getLanguage("DefaultName")
end

--- 图片设置接口
function HelperFunc.SetIconById(icon,id,type)
	if icon == nil or HelperFunc.IsNull(icon) then
		return
	end
	if not id then
		return
	end
	local atlas = ""
	local path = ""
	if type == EnumConst.ItemShowType.ITEM then
		atlas = EnumConst.AtlasPath.ItemAtlas
		local cfg = dataTable.getRow("t_item", id)
		if cfg then
			path = cfg.f_Icon
		end
	elseif type == EnumConst.ItemShowType.EQUIP then
		atlas = EnumConst.AtlasPath.ItemAtlas
		local cfg = dataTable.getRow("t_equip", id)
		if cfg then
			path = cfg.f_EquipSuitlcon
		end
	elseif type == EnumConst.ItemShowType.SKILL then
		atlas = EnumConst.AtlasPath.SkillAtlas
		local cfg = dataTable.getRow("t_skillshow", id)
		if cfg then
			path = cfg.f_SkillIcon
		end
	elseif type == EnumConst.ItemShowType.Title then
		atlas = EnumConst.AtlasPath.ICONAtlas
		local cfg = dataTable.getRow("t_item", id)
		if cfg then
			path = cfg.f_Icon
		end
	else
		logError("[error] need override type :"..type)
		return
	end
	if (path == "") then
		logError("can not find cfg by id :"..id)
		return
	end
	icon.url = atlas .. path;
end

--- 图片设置接口
function HelperFunc.SetIcon(icon,path,type)
	if icon == nil or HelperFunc.IsNull(icon) then
		return
	end
	local atlas = ""
	if type == EnumConst.ItemShowType.ITEM then
		atlas = EnumConst.AtlasPath.ItemAtlas
	elseif type == EnumConst.ItemShowType.EQUIP then
		atlas = EnumConst.AtlasPath.ItemAtlas
	elseif type == EnumConst.ItemShowType.SKILL then
		atlas = EnumConst.AtlasPath.SkillAtlas
	elseif type == EnumConst.ItemShowType.ICON then
		atlas = EnumConst.AtlasPath.ICONAtlas
	elseif type == 0 then
		-- path为全路径
	else
		atlas = EnumConst.AtlasPath.ItemAtlas
	end
	icon.url = atlas .. path;
end

--- 获取灰态shader
local grayMaterial = nil
function HelperFunc.GetGrayMaterial()
	if grayMaterial == nil then
		grayMaterial = Material(Shader.Find("UI/Default Grey"))
	end
	return grayMaterial
end

--- 获取当前 版本内最大星级
function HelperFunc.GetMaxStarLev()
	return HelperFunc.GetGlobalNumVlue(93)
end

--- 设置icon的显示状态
function HelperFunc.ShowIcon(icon, show)
	if icon == nil or HelperFunc.IsNull(icon) then
		return
	end
	icon.gameObject:SetActive(show)
end

--- 是否是自己
function HelperFunc.IsOwn(playerId)
	return logicMgr.HeroManager.GetRoleInfo().playerId == playerId
end

--- 随机方向
function HelperFunc.RandomDir(trans)
	if HelperFunc.IsNull(trans) then 
		return
	end
	local random = math.random()
	local oriAngles = trans.localEulerAngles
	oriAngles.y = random >= 0.5 and 180 or 0
	trans.localEulerAngles = oriAngles
end

--- 设置层级
--- inChild 递归设置
function HelperFunc.SetLayer(obj, layer, inChild)
	if not obj then 
		return
	end
	obj.gameObject.layer = layer
	if inChild then 
		local objTrans = obj.transform
		local childCount = objTrans.childCount
		for i = 0, childCount - 1 do
			HelperFunc.SetLayer(objTrans:GetChild(i),layer,true)
		end
	end
end

--- 判断是否为空
--- 使用这种方式判断的地方 都是提前删除了对象 逻辑有问题
function HelperFunc.IsNull(obj)
	if obj == nil then 
		return true
	end

	local _type = type(obj)
	if _type == "table" then
		return false
	end
	if _type == "userdata" then
		return Util.IsNull(obj)
	else
		return false
	end
	-- local tv = tostring(obj) 
	-- return tv == nil or tv == "null" or Util.IsNull(obj)
	
end

--- 将text分割成以sep作为分隔符的数字数组
function HelperFunc.GetNumberList(text, sep)
	if sep == nil then sep = "," end
	local list = string.split(text, sep)
	for i,v in ipairs(list) do
		list[i] = tonumber(v)
	end
	return list
end

function HelperFunc.GetSplit(text, sep)
	if sep == nil then sep = "," end
	local list = string.split(text, sep)
	local newList = {}
	for i,v in ipairs(list) do
		if v ~= "" then
			newList[i] = v
		end

	end
	return newList
end
function HelperFunc.ListTransitionStop(listObj)
	local num = listObj.numChildren
	for i=0,num-1 do
		local obj = listObj:GetChildAt(i)
		---@type FairyGUI.Transition
		local ctrl = obj:GetTransition("Effect_List")
		if ctrl then
			ctrl:Stop()
			obj.alpha = 1
		end
	end
end
--list动效
function HelperFunc.ListTranstionPlay(listObj,call)
	local num = listObj.numChildren
	for i=0,num-1 do
		local obj = listObj:GetChildAt(i)
		local ctrl = obj:GetTransition("Effect_List")
		if ctrl then
			obj.alpha = 0
			listObj.touchable = false
			ctrl:Play(1,0.02*i,function()
				obj.alpha = 1
				if i== num-1 then
					listObj.touchable = true
					if call then
						call()
					end
				end
			end)
		end
	end
end
--颜色值转rgba
function HelperFunc.GetColorOfRGB(str)
	local colorlist = {}
	local index = 1
	while index < string.len(str) do
		local tempstr = string.sub(str, index, index + 1)
		table.insert(colorlist, tonumber(tempstr, 16))
		index = index + 2
	end
	return colorlist[1] or 0, colorlist[2] or 0, colorlist[3] or 0, colorlist[4] or 255
end
--- 是否是FGUI对象
function HelperFunc.IsFGUIObj(obj)
	if type(obj) ~= "userdata" then
		return false
	end
	local name = obj[".name"]
	if name ~= nil then
		local nameSlip = HelperFunc.GetSplit(name,".")
		if nameSlip[1] ~= nil and nameSlip[1] == "FairyGUI" then
			return true
		end
	end
	return false
end

--- 旧UI流程的创建方式 
--- 原理 设置当前环境 所有的当前环境的全局变量将会被管理起来 然后走统一的卸载流程
function HelperFunc.SetUIEnv(t)
	t = Interface(t,UIComponentInterface)
	t = setmetatable(t,{__index = _G,__newindex = t.__newindex})
	setfenv(2, t)
	return t
end

------------------------------------- 货币显示相关 -------------------------------------
--- 根据具体需求 国内版本使用四位分级法 国外版本使用三位分级法
function HelperFunc.FormatResourceNum(num, no100Million)
	if EnumConst.ChoseLanguage == EnumConst.LanguageType.CN then 
		return HelperFunc.Format4ResourceNum(num, no100Million)
	else
		return HelperFunc.Format3ResourceNum(num)
	end
	return num
end
--- 三位分级法
function HelperFunc.Format3ResourceNum(num)
	local tempValue = 9999999999
	if num >= tempValue then 
		num = tempValue
	end
	-- m
	tempValue = 1000000
	if num > tempValue then 
		return math.floor(num / tempValue) .. "m"
	end
	-- k
	tempValue = 100000
	if num >= tempValue then 
		return math.floor(num / 1000) .. "k"
	end	
	return num
end
--- 四位分级法
function HelperFunc.Format4ResourceNum(num, no100Million)
	if num then
		local tempValue = 1999999999999
		num = tonumber(tostring(num)); --操蛋的long
		if num and num >= tempValue then
			num = tempValue
		end
		-- 亿
		if not no100Million then
			tempValue = 1000000000
			if num >= tempValue then
				return Mathf.Round(num / 100000000) .. getLanguage("Sys_Num_Unit2")
			end
		end
		-- 万
		tempValue = 100000
		if num >= tempValue then
			return Mathf.Round(num / 10000) .. getLanguage("Sys_Num_Unit1")
		end
		return num
	end
	return 0;
end
------------------------------------- 货币显示相关 ------------------------------------- 
--- 返回章节组
function HelperFunc.GetChaterGroup(chapterId)
	local chapterGroup = 1
	for index, value in pairs(G.dataTable.t_mapdeploy) do
		local plotIds = decodeJsonStrToTabel(value.f_PlotId)
		if table.contains(plotIds,chapterId) then 
			return index
		end
	end
	return chapterGroup
end
------------------------------------- 时间相关 ------------------------------------- 
--- second 秒
---返回 00:00:00
function HelperFunc.GetTimeStr(second)
	second = math.floor(second)
	if second <= 0 then
		return "00:00:00"
	end
	local hour = math.floor(second / 3600)
	local mod = second % 3600
	local minute =  math.floor(mod /60)
	second = mod % 60
	return string.format("%02d:%02d:%02d",hour,minute,second)
end
---返回 00:00
function HelperFunc.GetMinuteSecond(second)
	if second <= 0 then
		return "00:00"
	end
	local minute =  math.floor(second /60)
	second = second % 60
	return string.format("%02d:%02d",minute,second)
end
--- second 秒
---超过天 显示x天  否则显示 00:00:00
function HelperFunc.GetTimeStr2(second)
	second = math.floor(second)
	if second <= 0 then
		return "00:00:00"
	end
	local day = math.floor(second / (24*3600))
	if day > 0 then
		return string.format(getLanguage("Sys_Time_Day"),day)
	end
	local hour = math.floor(second / 3600)
	local mod = second % 3600
	local minute =  math.floor(mod /60)
	second = mod % 60
	return string.format("%02d:%02d:%02d",hour,minute,second)
end
--- surpTime 剩余时间
--- return XX天XX时 or XX时XX分 or XX分XX秒
function HelperFunc.GetSurpTimeStr(surpTime)
	local key1 = 0
	local key2 = 0
	local value1 = 0
	local value2 = 0

	-- 天
	local surpDay = math.floor(surpTime / 24 / 3600)
	-- 时
	local surpHour = math.floor((surpTime - surpDay*24*3600) / 3600)
	if surpDay > 0 then 
		key1 = "Sys_Time_Day"
		key2 = "Sys_Time_Hour"
		value1 = surpDay
		value2 = surpHour
	else
		-- 分
		local surpMin = math.floor((surpTime - surpDay*24*3600 - surpHour*3600)/60)
		if surpHour > 0 then 
			key1 = "Sys_Time_Hour"
			key2 = "Sys_Time_Minute"
			value1 = surpHour
			value2 = surpMin
		else
			-- 秒
			local surpSec = surpTime - surpDay*24*3600 - surpHour*3600 - surpMin*60
			key1 = "Sys_Time_Minute"
			key2 = "Sys_Time_Second"
			value1 = surpMin
			value2 = surpSec
		end
	end
	return string.format(getLanguage(key1)..getLanguage(key2),value1,value2)
end

--- 获取多少天后还剩余的时间(秒)
--- startTime 开始时间(秒)
--- endDay 结束天数(天)
--- return 剩余时间(秒)
function HelperFunc.GetSurpTime(startTime,endDay)
	if startTime == nil then
		startTime = 0
	end
	local serverTime = HelperFunc.GetServerTime()
	local createDetailTime = os.date("*t",startTime)
	local startcreateDayTime = startTime - createDetailTime.hour * 3600 - createDetailTime.min * 60 - createDetailTime.sec
	local surpTime = startcreateDayTime + endDay * 24 * 3600 - serverTime
	return surpTime < 0 and 0 or surpTime
end
------------------------------------- 时间相关 -------------------------------------
---@param targetObj GObject
---@param items number[]
function HelperFunc.FlyToBagByItemData(items,parentRoot,poolPar,targetObj,transition)
	if table.getn(items) > 0 then
		local w = Screen.width
		local h = Screen.height
		if w < 1080 then
			w = 1080
		end
		if h < 1920 then
			h = 1920
		end
		local startPos = parentRoot.parent:TransformPoint(Vector2(w / 2, h / 3), parentRoot)
		local endPos = targetObj.parent:TransformPoint(Vector2(targetObj.x, targetObj.y), parentRoot)
		local list = {}
		for k,itemID in pairs(items) do
			if itemID ~= 1 and itemID ~= 3 and itemID ~= 5 and itemID ~=6 then
				local scriptId = 0
				local type = -1
				local flag = false
				if logicMgr.ItemManager.IsEquip(itemID) then
					type = EnumConst.ItemTypeEnum.Equip
				else
					local cfg = dataTable.getRow("t_item", itemID)
					if cfg then
						type = cfg.f_BagType
						scriptId = cfg.f_ScriptId
					end
				end
				if EnumConst.ItemTypeEnum.Normal == type and scriptId == 300001 then--随机装备
					flag = true
				end
				if flag or (EnumConst.ItemTypeEnum.Hero == type or  EnumConst.ItemTypeEnum.Equip == type
						or EnumConst.ItemTypeEnum.Fragment == type or EnumConst.ItemTypeEnum.Hero == type)  then
					table.insert(list,itemID)
				end
			end
		end
		HelperFunc.FlyToBagByItemData2(list, parentRoot, poolPar, startPos, endPos, transition);
	end
end
--- 道具飞行轨迹
-- @param items:table 物品数据列表,t_item中的id
-- items = {[1]=1,[2]=2,[3]=300100, [4]=200315}
local list = {}
---@param items number[]
function HelperFunc.FlyToBagByItemData2(items, parentRoot,poolPar,startPos,endPos,trans,flyTime)
	if not items or #items <= 0 then return end
	local count = 0
	local index = 0
	for k, itemID in pairs(items) do
		local cfg,type,icon,scriptId,quality
		if logicMgr.ItemManager.IsEquip(itemID) then
			cfg = dataTable.getRow("t_equip", itemID)
			type = EnumConst.ItemTableEnum.Equip
			icon = cfg.f_EquipSuitlcon
			quality = cfg.f_EquipQuality
		else
			cfg = dataTable.getRow("t_item", itemID)
			if cfg then
				type = cfg.f_BagType
				icon = cfg.f_Icon
				scriptId = cfg.f_ScriptId
				quality = cfg.f_Quality
			end
		end
		if cfg then
			index = index + 1

			local itemItem = (list[index] and list[index].obj) or newGComponent("wardicon","UIFuncMenu")
			itemItem:GetChild("icon").url = "ui://ItemAtlas/"..icon;
			itemItem:GetChild("frame").url = EnumConst.AtlasPath.ICONAtlas..Config.IconFrame[quality];
			itemItem:GetChild("quality").url = EnumConst.AtlasPath.ICONAtlas..Config.IconQuality[quality];
			parentRoot:AddChild(itemItem);
			if not (list[index] and list[index].obj) then
				table.insert(list, {obj = itemItem})
			end
			count = count + 1
			itemItem:SetPosition(startPos.x,startPos.y, 0)
			if #list > 10 then
				break;
			end
		end
	end
	if #list > 0 then
		for i=1,#list do
			flyTime = flyTime or 1
			local move = list[i].obj:TweenMove(endPos.x,endPos.y,flyTime):OnComplete(function ()
				if trans then
					trans:Play()
				end
				if list[i] then
					poolPar:AddChild(list[i].obj)
				end
			end);
			move:SetEase(EaseType.CircIn);
		end
	end
end
--飞上面
function HelperFunc.FlyToHeadItemData(items,goldpar,diamodpar,exppar,originStartPos)
	if not items or #items <= 0 then return end
	local list = {}
	for _, itemID in pairs(items) do
		if itemID == 3 then
			list["gold"] = 1;
		end

		if itemID == 1 then
			list["diamold"] = 1;
		end

		if itemID == 6 or itemID == 5 then
			list["exp"] = 1;
		end
	end

	if list["gold"] and list["gold"] == 1 then
		HelperFunc.CreateParticle(goldpar,"EFF_Battle_CollectGold");
	end

	if list["diamold"] and list["diamold"] == 1 then
		HelperFunc.CreateParticle(diamodpar,"EFF_Battle_CollectDiamond");
	end

	if list["exp"] and list["exp"] == 1 then
		HelperFunc.CreateParticle(exppar,"EFF_Battle_CollectExp");
	end
	AudioManager.Play(AudioManager.Play_UI_ADV_Award_Get)
end

local sprines = {};
local drawWrappers = {};
function HelperFunc.CreateParticle(par,spineName)
	resMgr:LoadModelPrefab("Fx/"..spineName, function(go)
		--[[local drawWrapper = drawWrappers[spineName];
		if (drawWrapper == nil) then
			drawWrapper = GoWrapper.New();
			drawWrappers[spineName] = drawWrapper
		end]]
		if (sprines[spineName] ~= nil) then
			destroyImmediate(sprines[spineName]);
			sprines[spineName] = nil
		end
		sprines[spineName] = newObject(go);
		sprines[spineName].name = spineName;
		sprines[spineName]:AddComponent(TCanvas);
		local drawWrapper = GoWrapper.New()
		drawWrapper:SetWrapTarget(sprines[spineName], false)
		Util.Lua_SetLocalPositionXYZ(sprines[spineName],0,0,0);
		Util.Lua_SetLocalScaleXYZ(sprines[spineName],0.8,0.8,0);
		par:SetNativeObject(drawWrapper)
    end)
end
function HelperFunc.ClearFlyList()
	table.clear(list)
end
function HelperFunc.ClearParticles()
	for key, value in pairs(sprines) do
		destroy(value)
	end
	table.clear(sprines)
	--[[for key, value in pairs(drawWrappers) do
		if not HelperFunc.IsNull(value) then
			value:Dispose();
		end
	end
	table.clear(drawWrappers)]]
end
--[[function HelperFunc.Dispose()
	for key, value in pairs(sprines) do
		destroy(value)
	end
	table.clear(sprines)
	for key, value in pairs(drawWrappers) do
		if not HelperFunc.IsNull(value) then 
			value:Dispose();
		end
	end
	table.clear(drawWrappers)
end]]

function HelperFunc.UnloadUnusedAssets(clearType)
	--HelperFunc.Dispose()
	--printError("垃圾回收前==",collectgarbage("count"))
	collectgarbage("collect")
	--printError("垃圾回收后=====",collectgarbage("count"))
    Util.UnloadUnusedAssets(clearType)
end

function HelperFunc.UnloadLihui()
	--HelperFunc.Dispose()
	--printError("垃圾回收前==",collectgarbage("count"))
	--collectgarbage("collect")
	--printError("垃圾回收后=====",collectgarbage("count"))
    Util.UnloadLihui()
end

function HelperFunc.UnloadSingleLihui(name)
    --Util.UnloadSingleLihui(name)
end

function HelperFunc.UnloadBattleRes()
	--collectgarbage("collect")
	Util.UnloadBattleRes()
end

function HelperFunc.OpenUILoading(func)
	showUI(PanelNames.UILoadingAnimation, nil, func);
end

function HelperFunc.CloseUILoading()
	if isOpenUI(PanelNames.UILoadingAnimation) then
		CtrlManager.GetCtrl(PanelNames.UILoadingAnimation):showCloseCloud();
	end
end

function HelperFunc.GetItemNameWithoutColor(name)
	local res = ""
	if name ~= nil and name ~= "" then
		local str = string.split(name,']')[2]
		if str then
			res = string.split(str,'[')[1]
		end
	end
	return res
end

--- 重置主城模式
function HelperFunc.ResetCityMode(mode)
	if not logicMgr.FuncOpenManager.isOpen(Config.FuncOpenType.CityModeSwitch, false) then
		return
	end
	SetPlayerPrefs("city_mode", mode)
	FireEvent(Config.EventType.CityModeReset,mode)
end

return HelperFunc